"""
主题管理系统
负责管理应用的主题配置和切换，支持Element UI完整颜色系统
"""

import json
import os
from typing import Dict, List, Optional, Callable, Any, Union
from .themes import BUILT_IN_THEMES, ELEMENT_DEFAULT_THEME, Theme as GlobalTheme


class ThemeChangeEvent:
    """主题变更事件"""
    
    def __init__(self, old_theme: str, new_theme: str, theme_data: dict):
        self.old_theme = old_theme
        self.new_theme = new_theme
        self.theme_data = theme_data
        self.timestamp = None
        

class ThemeManager:
    """
    Element UI风格主题管理器
    
    功能：
    - 管理多个主题配置
    - 支持主题热切换
    - 提供主题变量访问
    - 支持自定义主题注册
    - 主题变更事件通知
    """
    
    def __init__(self):
        self.current_theme: Optional[str] = None
        self.available_themes: Dict[str, dict] = {}
        self.theme_variables: Dict[str, Any] = {}
        self._observers: List[Callable] = []
        
        # 注册内置主题
        self._register_built_in_themes()
        
        # 默认加载Element UI默认主题
        self.load_theme("element-default")
    
    def _register_built_in_themes(self):
        """注册内置主题"""
        for theme_name, theme_config in BUILT_IN_THEMES.items():
            self.available_themes[theme_name] = theme_config
    
    def register_theme(self, theme_config: Union[str, dict]) -> bool:
        """
        注册新主题
        
        Args:
            theme_config: 主题配置字典或JSON文件路径
            
        Returns:
            bool: 注册成功返回True，失败返回False
        """
        try:
            if isinstance(theme_config, str):
                # 如果是文件路径，则加载文件
                if os.path.exists(theme_config):
                    with open(theme_config, 'r', encoding='utf-8') as f:
                        theme_config = json.load(f)
                else:
                    raise FileNotFoundError(f"主题文件不存在: {theme_config}")
            
            theme_name = theme_config.get('name')
            if not theme_name:
                raise ValueError("主题配置缺少name字段")
            
            # 验证主题配置结构
            if not self._validate_theme_config(theme_config):
                raise ValueError(f"主题配置无效: {theme_name}")
            
            self.available_themes[theme_name] = theme_config
            return True
            
        except Exception as e:
            print(f"注册主题失败: {e}")
            return False
    
    def _validate_theme_config(self, theme_config: dict) -> bool:
        """验证主题配置结构"""
        required_fields = ['name']
        
        for field in required_fields:
            if field not in theme_config:
                return False
        
        # 验证colors字段（如果存在）
        if 'colors' in theme_config:
            colors = theme_config['colors']
            if not isinstance(colors, dict):
                return False
        
        return True
    
    def load_theme(self, theme_name: str) -> bool:
        """
        加载指定主题
        
        Args:
            theme_name: 主题名称
            
        Returns:
            bool: 加载成功返回True，失败返回False
        """
        if theme_name not in self.available_themes:
            print(f"主题不存在: {theme_name}")
            return False
        
        old_theme = self.current_theme
        theme_config = self.available_themes[theme_name]
        
        # 更新当前主题
        self.current_theme = theme_name
        
        # 展平主题变量（支持嵌套结构）
        self.theme_variables = self._flatten_theme_variables(theme_config)
        
        # 更新全局主题访问器
        GlobalTheme.set_current_theme(theme_name)
        
        # 触发主题变更事件
        self._notify_theme_changed(old_theme, theme_name, theme_config)
        
        return True
    
    def _flatten_theme_variables(self, theme_config: dict) -> dict:
        """
        展平主题变量为扁平结构，便于访问
        
        例如：
        {
          "colors": {"primary": "#409EFF"},
          "sizes": {"base": "14px"}
        }
        ->
        {
          "colors.primary": "#409EFF",
          "sizes.base": "14px",
          "primary": "#409EFF",  # 简化访问
          "base": "14px"
        }
        """
        variables = {}
        
        def flatten(obj, prefix=''):
            for key, value in obj.items():
                full_key = f"{prefix}.{key}" if prefix else key
                
                if isinstance(value, dict):
                    # 递归处理嵌套字典
                    variables[full_key] = value
                    flatten(value, full_key)
                else:
                    # 添加完整路径和简化路径
                    variables[full_key] = value
                    variables[key] = value  # 简化访问
        
        # 展平所有字段
        flatten(theme_config)
        
        return variables
    
    def switch_theme(self, theme_name: str) -> bool:
        """切换主题（load_theme的别名）"""
        return self.load_theme(theme_name)
    
    def get_variable(self, variable_name: str, default: Any = None) -> Any:
        """
        获取主题变量值
        
        支持多种访问方式：
        - get_variable("primary") -> "#409EFF"
        - get_variable("colors.primary") -> "#409EFF"
        - get_variable("font-size-base") -> "14px"
        """
        # 尝试多种键名格式
        possible_keys = [
            variable_name,
            variable_name.replace('-', '_'),  # font-size-base -> font_size_base
            variable_name.replace('_', '-'),  # font_size_base -> font-size-base
        ]
        
        for key in possible_keys:
            if key in self.theme_variables:
                return self.theme_variables[key]
        
        return default
    
    def get_color(self, color_name: str, default: str = None) -> str:
        """获取颜色变量"""
        # 优先从colors命名空间查找
        color_key = f"colors.{color_name}"
        if color_key in self.theme_variables:
            return self.theme_variables[color_key]
        
        # 回退到直接查找
        return self.get_variable(color_name, default)
    
    def get_size(self, size_name: str, default: str = None) -> str:
        """获取尺寸变量"""
        # 优先从sizes命名空间查找
        size_key = f"sizes.{size_name}"
        if size_key in self.theme_variables:
            return self.theme_variables[size_key]
        
        # 回退到直接查找
        return self.get_variable(size_name, default)
    
    def get_font(self, font_name: str, default: str = None) -> str:
        """获取字体变量"""
        font_key = f"fonts.{font_name}"
        if font_key in self.theme_variables:
            return self.theme_variables[font_key]
        
        return self.get_variable(font_name, default)
    
    def get_shadow(self, shadow_name: str, default: str = None) -> str:
        """获取阴影变量"""
        shadow_key = f"shadows.{shadow_name}"
        if shadow_key in self.theme_variables:
            return self.theme_variables[shadow_key]
        
        return self.get_variable(shadow_name, default)
    
    def get_component_config(self, component_name: str) -> dict:
        """获取组件特定配置"""
        component_key = f"components.{component_name}"
        return self.theme_variables.get(component_key, {})
    
    def get_available_themes(self) -> List[str]:
        """获取可用主题列表"""
        return list(self.available_themes.keys())
    
    def get_current_theme(self) -> Optional[str]:
        """获取当前主题名称"""
        return self.current_theme
    
    def get_theme_info(self, theme_name: str) -> Optional[dict]:
        """获取主题基本信息"""
        if theme_name not in self.available_themes:
            return None
        
        theme_config = self.available_themes[theme_name]
        return {
            "name": theme_config.get("name"),
            "description": theme_config.get("description", ""),
            "version": theme_config.get("version", "1.0.0"),
        }
    
    def export_theme(self, theme_name: str, file_path: str) -> bool:
        """导出主题配置到文件"""
        if theme_name not in self.available_themes:
            return False
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(self.available_themes[theme_name], f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            print(f"导出主题失败: {e}")
            return False
    
    def clone_theme(self, source_theme: str, new_theme_name: str, modifications: dict = None) -> bool:
        """
        克隆主题并创建新主题
        
        Args:
            source_theme: 源主题名称
            new_theme_name: 新主题名称
            modifications: 需要修改的配置
        """
        if source_theme not in self.available_themes:
            return False
        
        # 深拷贝源主题配置
        import copy
        new_theme_config = copy.deepcopy(self.available_themes[source_theme])
        
        # 更新主题名称
        new_theme_config["name"] = new_theme_name
        
        # 应用修改
        if modifications:
            self._apply_modifications(new_theme_config, modifications)
        
        # 注册新主题
        return self.register_theme(new_theme_config)
    
    def _apply_modifications(self, theme_config: dict, modifications: dict):
        """递归应用主题修改"""
        for key, value in modifications.items():
            if '.' in key:
                # 处理嵌套键名，如 "colors.primary"
                parts = key.split('.')
                current = theme_config
                for part in parts[:-1]:
                    if part not in current:
                        current[part] = {}
                    current = current[part]
                current[parts[-1]] = value
            else:
                theme_config[key] = value
    
    def subscribe_theme_change(self, callback: Callable[[ThemeChangeEvent], None]):
        """
        订阅主题变更事件
        
        Args:
            callback: 回调函数，接收ThemeChangeEvent参数
        """
        if callback not in self._observers:
            self._observers.append(callback)
    
    def unsubscribe_theme_change(self, callback: Callable):
        """取消订阅主题变更"""
        if callback in self._observers:
            self._observers.remove(callback)
    
    def _notify_theme_changed(self, old_theme: str, new_theme: str, theme_data: dict):
        """通知主题变更"""
        event = ThemeChangeEvent(old_theme, new_theme, theme_data)
        
        for callback in self._observers:
            try:
                callback(event)
            except Exception as e:
                print(f"主题变更回调执行失败: {e}")


# =============================================================================
# 全局主题管理器实例
# =============================================================================

# 创建全局主题管理器实例
theme_manager = ThemeManager()

# 便捷的全局函数
def get_current_theme() -> Optional[str]:
    """获取当前主题名称"""
    return theme_manager.get_current_theme()

def switch_theme(theme_name: str) -> bool:
    """切换主题"""
    return theme_manager.switch_theme(theme_name)

def get_theme_variable(variable_name: str, default: Any = None) -> Any:
    """获取主题变量"""
    return theme_manager.get_variable(variable_name, default)

def get_theme_color(color_name: str, default: str = None) -> str:
    """获取主题颜色"""
    return theme_manager.get_color(color_name, default)

def get_theme_size(size_name: str, default: str = None) -> str:
    """获取主题尺寸"""
    return theme_manager.get_size(size_name, default)